界面布局 - Flexbox

前面介绍的 display 类型 block 和 inline , 属于该元素的 外部 显示类型

外部显示类型决定了元素作为一个整体 如何显示在界面上 (新开一行,还是跟随前面的元素)


接下来我们会介绍元素的内部显示类型,也就是该元素的内部子元素 怎么布局。

包括:内部子元素 为几行几列,子元素对齐,居左,局右等。

这些布局,以前主要通过CSS的 floatposition 实现,但是它们有很多局限,很多布局实现起来很困难。


新的CSS规范推出了 grid - 网格布局flexbox - 弹性盒子布局 ,很多布局场景实现起来非常方便。

本章先学习 flexbox - 弹性盒子布局 (简称弹性布局)

基本概念

先看这段HTML


<head>
  <style>
  .wrapper{
    display:flex; 
    gap: .5em;
    flex-direction:row;
  }

  .wrapper > div {
    border: 1px solid teal;
  }
  </style>
</head>  
<body>
  <div class="wrapper">  
    <div>1</div>
    <div>2</div>
    <div> 3
      <br>3
      <br>3
      <br>3
    </div>
    <div>444</div>
    <div>5</div>
    <div>6</div>
    <div>7</div>
    <div>8888888888888</div>
    <div>99999999999999999999999999999999999</div>
    <div>aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa</div>
    <div>bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb</div>
  </div>
</body>  

div.wrapperdisplay 值为 flex ,指定了

  • 内部显示规则是 flexbox 布局

  • 外部显示规则是 block

  • 该元素本身是一个 容器

    flexbox 容器 (container) 是整个布局的最外层包含元素

  • 该元素的直接子元素是一个个 flex元素


gap 指定了 flex元素 的 间距


flex元素 的布局方向是由 容器的 flex-direction 定义的

flex-direction 定义的 也就是 主轴 方向

比如 flex-direction:row 表示主轴是 水平方向正向

什么是正向? 就是网页语言对应的文字书写方向,通常是从左到右

但是有的语言,比如阿拉伯文字正向就是从右到左。


主轴垂直的方向线,就是 从轴,也有翻译为 交叉轴


主轴定义了 内部 flex元素 的 布局方向,

如果正向是从左到右, flex-direction:row 表示 子项元素 的布局方向是 依次从左到右


主轴由 flex-direction 定义,可以取4个值:

  • row

    主轴是 横向正向(通常是从左到右)

  • row-reverse

    主轴是 横向反向(通常是从右到左)

  • column

    主轴是 纵向正向(通常是从上到下)

  • column-reverse

    主轴是 纵向反向(通常是从下到上)

大家可以尝试一下,把上面的 flex-direction 依次改为这4个值,显示结果分别是什么



上面的HTML示例,可以发现:

如果有的 flex元素 的内容 宽度 比其它的宽, 只是这个 flex元素 自动拓宽。


但是,缺省情况下,如果有的 flex元素 的内容 高度 比其它的高,

整个行所有的 flex元素 自动扩展为同样高度。 结果就是所有的 flex元素 都保持和最高的 flex元素 一致。

如果要让各 flex元素 保持各自的高度,可以设置 align-items 对齐属性,这个后面会讲。

自动换行

上面的示例中,如果container 的宽度不足以存放 所有 flex元素 , 就会出现滚动条。

这样确保所有的 flex元素 都在一行。

如果,我们需要的效果是,超出 container 宽度后,自动换行,可以加上 flex-wrap: wrap 属性

{
  .wrapper {
    display: flex;
    gap: .5em; 
    flex-direction: row;
    flex-wrap: wrap
  }
}

flex-direction 和 flex-wrap 属性如果需要一起指定,可以使用 flex-flow 来替代,如下

{
  .wrapper {
    display: flex;
    gap: .5em; 
    flex-flow: row wrap;
  }
}

flex元素 的属性

flex-basis

前面的例子中,一个 flex元素 的宽度是由其内容决定的。

如果一行放置了所有的 flex元素 还有剩余的空间,这些空间是没有使用的。

我们可以指定 flex元素 的 flex-basis 属性, 如果flex容器有剩余的空间, 这些元素可以分配剩余空间给这些 flex元素 ,最多到 flex-basis 指定的宽度。

比如

<div class="wrapper">  
  <div>1</div>
  <div>2</div>
  <div> 3
    <br>3
    <br>3
    <br>3
  </div>
  <div>444</div>
  <div style="flex-basis: 300px">5</div>
  <div style="flex-basis: 200px">6</div>
  <div style="flex-basis: 10px">777777777777777</div>
  <div>8888888888888</div>
</div>

大家可以拖拽窗口的宽度,看看宽度元素宽度变化的比例。

flex-grow

我们可以通过 flex元素 的 flex-grow 属性指定,如果有剩余空间,这个元素可以分配到多少的比例。

比如

<div class="wrapper">  
  <div>1</div>
  <div>2</div>
  <div> 3
    <br>3
    <br>3
    <br>3
  </div>
  <div>444</div>
  <div style="flex-grow: 3">5</div>
  <div style="flex-grow: 2">6</div>
  <div style="flex-grow: 1">7</div>
  <div>8888888888888</div>  
</div>

div 5、div 6、div 7 就会分别拿走 多余空间的 3/6 、 2/6 、1/6


大家可以拖拽窗口的宽度,看看元素宽度变化的比例。


如果不设置,flex-grow 使用缺省值 0

flex-shrink

我们可以指定 flex元素 的 flex-shrink 属性,这个属性和 flex-grow 属性正好相反。

flex-shrink 指定如果 flex容器 空间 比所有 flex元素 空间总和小,这个元素空间缩减的比例。

比如

<div class="wrapper">  
  <div>1</div>
  <div>2</div>
  <div> 3
    <br>3
    <br>3
    <br>3
  </div>
  <div>444</div>
  <div>5</div>
  <div>6</div>
  <div style="flex-shrink: 1;flex-basis:300px">777777777777777</div>
  <div style="flex-shrink: 3;flex-basis:300px">8888888888888</div>
</div>

大家可以拖拽窗口的宽度,看看元素宽度减小的比例。

当然,优先确保这些元素内容能够显示, flex元素 不会缩减到元素内容不够显示宽度的情况。


如果不设置,flex-shrink 使用缺省值 1



flex-grow、 flex-shrink、 flex-basis 3 个元素的指定,可以用 flex 一起指定,语法更简洁

{
  flex-grow : 2; 
  flex-shrink: 1;
  flex-basis:300px
}

等价于

{
  flex : 2 1 300px
}

比如

<div class="wrapper">  
  <div>1</div>
  <div>2</div>
  <div> 3
    <br>3
    <br>3
    <br>3
  </div>
  <div>444</div>
  <div>5</div>
  <div>6</div>
  <div style="flex : 1 1 200px">777777777777777</div>
  <div style="flex : 2 1 200px">8888888888888</div>
</div>

从轴对齐

下面这个示例


<head>
  <style>
  .wrapper{
    display:flex; 
    gap: .5em;
    flex-direction:row;
  }

  .wrapper > div {
    border: 1px solid teal;
  }
  </style>
</head>  
<body>
  <div class="wrapper">  
    <div>1</div>
    <div>2</div>
    <div> 3
      <br>3
      <br>3
      <br>3
    </div>
    <div>444</div>
    <div>5</div>
    <div>6</div>
  </div>
</body>  


缺省情况下,如果有的 flex元素 的内容 高度比其它的高, 整个行所有的 flex元素 自动扩展为同样高度。 结果就是所有的 flex元素 都保持和最高的 flex元素 一致。

这是 container元素的 align-items 这个属性决定的。

align-items 属性控制 从轴线 方向的 flex元素 的对齐。

它的缺省值为 stretch ,表示所有 flex元素 伸展到和 container 一样,


还可以把 align-items 的值设置为

  • flex-start

    flex元素 和 container 的开始位置(从轴方向 起始位置)对齐

上例中就是上边对齐



  • flex-end

    flex元素 和 container 的结束位置(从轴方向 结束位置)对齐

上例中就是下边对齐



  • center

    flex元素 和 container 的中间位置(从轴方向 结束位置)对齐




主轴对齐

container元素的 justify-content 属性控制 主轴线 方向的 flex元素 的对齐。

比如下面的示例


<!DOCTYPE html>
<html>

<head>
  <style>
  .wrapper {
    display: flex;
    justify-content : flex-start;
    gap: .5em; 
    border: 1px dashed red
  }

  .wrapper > div {
    border: 1px solid teal;
  }
  </style>
</head>

<body>  

<div class="wrapper">  
  <div>1</div>
  <div>2</div>
  <div> 3
    <br>3
    <br>3
    <br>3
  </div>
  <div>444</div>
  <div>5</div>
  <div>6</div>
</div>

</body>
</html>

justify-content 属性的常见的取值为

  • flex-start

    flex元素 和 container 的 主轴方向开始位置 对齐

    上例中就是左边对齐

  • flex-end

    flex元素 和 container 的 主轴方向结束位置 对齐

上例中就是右边对齐



  • center

    flex元素 和 container 的 主轴方向中间位置 对齐

上例中就是中间对齐



  • space-between

    flex元素 均匀分布在主轴上,它们的间距相同

第一个 flex元素 和 container 的 主轴方向开始位置 平齐

最后一个 flex元素 和 container 的 主轴方向结束位置 平齐



  • space-around

    flex元素 均匀分布在主轴上,它们的间距相同

第一个 flex元素 和 container 的 主轴方向开始位置 的间距, 最后一个 flex元素 和 container 的 主轴方向结束位置 的间距 都是 flex元素 间距 的一半



  • space-evenly

    flex元素 均匀分布在主轴上,它们的间距相同

第一个 flex元素 和 container 的 主轴方向开始位置 的间距, 最后一个 flex元素 和 container 的 主轴方向结束位置 的间距 都是 flex元素 间距 相同